package dynamojunit;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.amazonaws.services.dynamodb.model.*;

public class TestClassTable
{
	public static final String TABLE_NAME = "TestClassTable"; 
	public static final String TABLE_KEY = "tcid";
	
	private static final String PASSED_METHODS_LIST_KEY = "passedMethodsList";
	private static final String FAILED_METHODS_LIST_KEY = "failedMethodsList";
	private static final String RUNTIME_KEY = "runtime";
	private static final String TOTAL_NUMBER_OF_PASSED_TESTS_TABLE_KEY ="okNum";
	private static final String TOTAL_NUMBER_OF_FAILED_TESTS_TABLE_KEY ="failNum";
	private static final String TEST_CLASS_NAME_KEY = "testClassName";
	private static final String TESTS_RESULTS_REMOTE_PATH_KEY = "resultXmlS3Path";
		
	public TestClassTable(boolean shouldInitTable)
	{
		if (shouldInitTable)
		{
			DynamoDbCommon.initTable(TABLE_NAME, TABLE_KEY);
		}
	}

	public Map<String,AttributeValue> readTestClassEntry(String tcid)
	{
		return DynamoDbCommon.readUniqueEntry(TABLE_NAME, TABLE_KEY, tcid);
	}
	
	public String readNumberOfPassedTests(Map<String,AttributeValue> entry_map)
	{
		AttributeValue val = DynamoDbCommon.readValuefromMap(entry_map, TOTAL_NUMBER_OF_PASSED_TESTS_TABLE_KEY);
		if (val!=null)
			return val.getN();
		else
			return "";
	}
	
	public String readNumberOfFailedTests(Map<String,AttributeValue> entry_map)
	{
		AttributeValue val = DynamoDbCommon.readValuefromMap(entry_map, TOTAL_NUMBER_OF_FAILED_TESTS_TABLE_KEY);
		if (val!=null)
			return val.getN();
		else
			return "";
	}
	
	public String readClassName(Map<String,AttributeValue> entry_map)
	{
		AttributeValue val = DynamoDbCommon.readValuefromMap(entry_map, TEST_CLASS_NAME_KEY);
		if (val!=null)
			return val.getS();
		else
			return "";
	}
	
	public String readRemoteS3TestResultsPath(Map<String,AttributeValue> entry_map)
	{
		AttributeValue val = DynamoDbCommon.readValuefromMap(entry_map, TESTS_RESULTS_REMOTE_PATH_KEY);
		if (val!=null)
			return val.getS();
		else
			return "";
	}
	
	public List<String> readPassedTestsList(Map<String,AttributeValue> entry_map)
	{
		AttributeValue val = DynamoDbCommon.readValuefromMap(entry_map, PASSED_METHODS_LIST_KEY);
		if (val!=null)
			return val.getSS();
		else
			return new ArrayList<String>();
	}
	
	public List<String> readFailedTestsList(Map<String,AttributeValue> entry_map)
	{
		AttributeValue val = DynamoDbCommon.readValuefromMap(entry_map, FAILED_METHODS_LIST_KEY);
		if (val!=null)
			return val.getSS();
		else
			return new ArrayList<String>();
	}
	
	public void startTestClassEntry(String tcid, String testClassName)
	{
		// {key: tcid}, {start timestamp}, {end timestamp}, {status: INITIAL/RUNNING/FINISHED}, {# total}, {# ok}, {# failed}, {Results XML Path in S3}
		
		Date dateNow = new Date();
		Map<String, AttributeValue> item = newItem(tcid, testClassName, dateNow.getTime(), 0, DynamoDbCommon.INITIAL);
		DynamoDbCommon.putItemWithConsistency(TABLE_NAME, TABLE_KEY, item);
	}
	
    private static Map<String, AttributeValue> newItem(String tcid, String testClassName, long startTime, long endTime, String tcStatus)
    {
        Map<String, AttributeValue> item = new HashMap<String, AttributeValue>();
        
        item.put(TABLE_KEY, new AttributeValue(tcid));
        item.put(TEST_CLASS_NAME_KEY, new AttributeValue(testClassName));
        item.put("startTime", new AttributeValue().withN(Long.toString(startTime)));
        item.put("tcStatus", new AttributeValue(tcStatus));
        
        // other attribs - not yet

        return item;
    }
    
    ////////////////////////////////
    
	public void updateTestNumbersAndStartRunning(String tcid, int totalNum)
	{
		Key key = new Key(new AttributeValue(tcid));
		Map<String, AttributeValueUpdate> updates = new HashMap<String, AttributeValueUpdate>();
		
		updates.put("tcStatus", new AttributeValueUpdate(new AttributeValue(DynamoDbCommon.RUNNING), "PUT"));
		updates.put("totalNum", new AttributeValueUpdate(new AttributeValue().withN(Integer.toString(totalNum)), "ADD"));
		
		updates.put(TOTAL_NUMBER_OF_PASSED_TESTS_TABLE_KEY, new AttributeValueUpdate(new AttributeValue().withN(Integer.toString(0)), "ADD")); 
		updates.put(TOTAL_NUMBER_OF_FAILED_TESTS_TABLE_KEY, new AttributeValueUpdate(new AttributeValue().withN(Integer.toString(0)), "ADD"));

		
		DynamoDbCommon.updateItem(TABLE_NAME, key, updates);
	}
	
	// TODO: add increment function for okNum and failNum
	
	public void updateTestClassResultAndFinish(String tcid, int okNum, int failNum, String resultXmlS3Path, List<String> list_of_all_failed_methods, List<String> list_of_all_passed_methods, long runtime)
	{
		Key key = new Key(new AttributeValue(tcid));
		Map<String, AttributeValueUpdate> updates = new HashMap<String, AttributeValueUpdate>();
		updates.put("tcStatus", new AttributeValueUpdate(new AttributeValue(DynamoDbCommon.FINISHED), "PUT"));
		
		updates.put(TOTAL_NUMBER_OF_PASSED_TESTS_TABLE_KEY, new AttributeValueUpdate(new AttributeValue().withN(Integer.toString(okNum)), "PUT")); 
		updates.put(TOTAL_NUMBER_OF_FAILED_TESTS_TABLE_KEY, new AttributeValueUpdate(new AttributeValue().withN(Integer.toString(failNum)), "PUT"));
		
		updates.put(TESTS_RESULTS_REMOTE_PATH_KEY, new AttributeValueUpdate(new AttributeValue(resultXmlS3Path), "PUT"));
		Date dateNow = new Date();
		updates.put("endTime", new AttributeValueUpdate(new AttributeValue().withN(Long.toString(dateNow.getTime())), "PUT"));
		
		if (!list_of_all_passed_methods.isEmpty())
			updates.put(PASSED_METHODS_LIST_KEY, new AttributeValueUpdate(new AttributeValue().withSS(list_of_all_passed_methods), "ADD"));
		if (!list_of_all_failed_methods.isEmpty())
			updates.put(FAILED_METHODS_LIST_KEY, new AttributeValueUpdate(new AttributeValue().withSS(list_of_all_failed_methods), "ADD"));
		updates.put(RUNTIME_KEY, new AttributeValueUpdate(new AttributeValue().withN(Long.toString(runtime)), "PUT")); 
		
		DynamoDbCommon.updateItem(TABLE_NAME, key, updates);
	}

}
